package com.ioffice.export.excel.engine.parse;



import java.util.List;

import org.apache.log4j.Logger;

import com.ioffice.exception.IOfficeException;
import com.ioffice.export.excel.sheet.SheetGeneric;
import com.ioffice.export.excel.sheet.cell.SheetCell;
import com.ioffice.export.excel.sheet.tree.ExcelSheetTree;
import com.ioffice.export.excel.sheet.tree.SheetCrossHeader;
import com.ioffice.export.excel.sheet.tree.SheetDataBody;
import com.ioffice.export.excel.sheet.tree.SheetLeftHeader;
import com.ioffice.export.excel.sheet.tree.SheetTopHeader;
import com.ioffice.export.excel.type.ExcelSheetTreeType;

public class ParseExcelSheetTree {

	private Logger log=Logger.getLogger(ParseExcelSheetTree.class);
	private String errorMsg="";
	
	/**
	 * 设置整个sheet的大小(范围)
	 * <p>
	 * <b>注：</b><br/>
	 *   设置ExcelSheet的这个范围
	 * </p>
	 * @param sheetTree
	 * @param treeType
	 */
	public void parseExcelSheetProperty(ExcelSheetTree sheetTree,ExcelSheetTreeType treeType ){
		sheetTree.setSheetName(treeType.getSheetName());
		sheetTree.setColCount(sheetTree.getSheetCrossHeader().getXspan()+sheetTree.getSheetTopHeader().getXspan());
		sheetTree.setRowCount(sheetTree.getSheetTitle().getYspan()+sheetTree.getSheetCrossHeader().getYspan()+sheetTree.getSheetLeftHeader().getYspan());
	}
	
	
	/**
	 * 解析SheetTitle的相关属性
	 * <p>
	 * <b>注：</b><br/>
	 *   设置SheetTitle的这个范围
	 * </p>
	 * @param excelSheet
	 */
	public void parseSheetTitleProperty(ExcelSheetTree sheetTree){
		int leftDeep=((SheetLeftHeader)sheetTree.getSheetLeftHeader()).getDeepCount();
		int xspan=((SheetTopHeader)sheetTree.getSheetTopHeader()).getLeafCount()+leftDeep;
		if(leftDeep==1)
			xspan=((SheetCrossHeader)sheetTree.getSheetCrossHeader()).getXspan()+((SheetTopHeader)sheetTree.getSheetTopHeader()).getLeafCount();
		sheetTree.getSheetTitle().setXspan(xspan);
		sheetTree.getSheetTitle().getChild().get(0).setXspan(xspan);
	}
	
	/**
	 * @see ParseExcelSheetTree.parseSheetTitleProperty(ExcelSheetTree sheetTree)
	 * @param sheetTree
	 * @param yspan 默认为 1
	 */
	public void parseSheetTitleProperty(ExcelSheetTree sheetTree,int yspan){
		parseSheetTitleProperty(sheetTree);
		if(yspan>1)
			sheetTree.getSheetTitle().setYspan(yspan);
	}
	
	/**
	 * 解析crossheader的相关属性
	 * <p>
	 * <b>注：</b><br/>
	 *   设置crossheader的这个范围
	 * </p>
	 * @param sheetTree
	 */
	public void parseSheetCrossHeaderProperty(ExcelSheetTree sheetTree){
		int x=sheetTree.getSheetTitle().getX();
		int y=sheetTree.getSheetTitle().getY()+sheetTree.getSheetTitle().getYspan();
		int xspan=((SheetLeftHeader)sheetTree.getSheetLeftHeader()).getDeepCount();
		
		
		int yspan=((SheetTopHeader)sheetTree.getSheetTopHeader()).getDeepCount();
		
		SheetCrossHeader cross=(SheetCrossHeader)sheetTree.getSheetCrossHeader();
		
		cross.setX(x);
		cross.setY(y);
		cross.setXspan(xspan);
		cross.setYspan(yspan);
		
		try{
			parseSheetGenericChildCellSpan(cross,true);
		}catch(IOfficeException iOfficeException){
			errorMsg="解析crossheader相关属性时，设置左表头span发生异常"+iOfficeException.toString();
			log.error(errorMsg);
			throw new RuntimeException(errorMsg);
		}
	}
	
	/**
	 * 设置上表头的相关属性
	 * <p>
	 * <b>注：</b><br/>
	 *   设置SheetTopHeader的这个范围
	 * </p>
	 * @param sheetTree
	 */
	public void parseSheetTopHeaderProperty(ExcelSheetTree sheetTree){
		SheetTopHeader topHeader=(SheetTopHeader)sheetTree.getSheetTopHeader();
		SheetCrossHeader crossHeader=(SheetCrossHeader)sheetTree.getSheetCrossHeader();
		int x=crossHeader.getX()+crossHeader.getXspan();
		int y=crossHeader.getY();
		int xspan=topHeader.getLeafCount();
		int yspan=topHeader.getDeepCount();
		
		topHeader.setX(x);
		topHeader.setY(y);
		topHeader.setXspan(xspan);
		topHeader.setYspan(yspan);
		try{
			parseSheetGenericChildCellSpan(topHeader, true);
		}catch(IOfficeException iOfficeException){
			errorMsg="解析topHeader相关属性时，设置上表头span发生异常"+iOfficeException.toString();
			log.error(errorMsg);
			throw new RuntimeException(errorMsg);
		}
		
	}
	/**
	 * setter left header basic property(x,y,xspan,yspan)
	 * <p>
	 * <b>注：</b><br/>
	 *   设置SheetLeftHeader的这个范围
	 * </p>
	 * @param sheetTree
	 */
	public void parseSheetLeftHeaderProperty(ExcelSheetTree sheetTree){
		SheetCrossHeader cross=(SheetCrossHeader)sheetTree.getSheetCrossHeader();
		SheetLeftHeader left=(SheetLeftHeader)sheetTree.getSheetLeftHeader();
		int x=cross.getX();
		int y=cross.getY()+cross.getYspan();
		
		int xspan=left.getDeepCount();
		int yspan=left.getLeafCount();
		
		left.setX(x);
		left.setY(y);
		left.setXspan(xspan);
		left.setYspan(yspan);
		
		try{
			parseSheetGenericChildCellSpan(left,false);
		}catch(IOfficeException iOfficeException){
			errorMsg="解析crossheader相关属性时，设置左表头span发生异常"+iOfficeException.toString();
			log.error(errorMsg);
			throw new RuntimeException(errorMsg);
		}
		
	}
	
	/**
	 * setter left header all childrens cell x(y) span
	 * @param left
	 */
	public void parseSheetLeftHeaderChildCellSpan(SheetLeftHeader left){
		int deepCount=left.getDeepCount();//得到整个Left的深度
		List<SheetCell> cells=left.getChild();
		for(SheetCell cell:cells){//一级
			int childCount=cell.getChildSize();
			if(childCount==0)
				cell.setXspan(deepCount);
			else
				parseLoopChildCellSpan(cell, deepCount);
		}
	}
	
	/**
	 * 设置sheetDataBody
	 * <p>
	 * <b>注：</b><br/>
	 *   设置databody的这个范围
	 * </p>
	 * @param sheetTree
	 */
	public void parseSheetDataBodyProperty(ExcelSheetTree sheetTree){
		SheetCrossHeader cross=(SheetCrossHeader)sheetTree.getSheetCrossHeader();
		SheetDataBody dataBody=(SheetDataBody)sheetTree.getSheetDataBody();
		int x=cross.getX()+cross.getXspan();
		int y=cross.getY()+cross.getYspan();
		int xspan=sheetTree.getSheetTopHeader().getXspan();
		int yspan=sheetTree.getSheetLeftHeader().getYspan();
		
		dataBody.setX(x);
		dataBody.setY(y);
		dataBody.setXspan(xspan);
		dataBody.setYspan(yspan);
	}
	
	
	
	private void parseLoopChildCellSpan(SheetCell cell,int deepCount){
		int currentLevel=cell.getLevel();
		List<SheetCell> cells=cell.getChild();
		for(SheetCell child:cells){
			int size=child.getChildSize();
			if(size==0)
				child.setLevel(deepCount-currentLevel-1);
			else
				parseLoopChildCellSpan(cell, deepCount);
		}
	}
	
	
	/**
	 * setter sheet compent child cell x(y)span
	 * @param generic
	 * @param top
	 * @throws IOfficeException
	 */
	private void parseSheetGenericChildCellSpan(SheetGeneric generic,boolean top) throws IOfficeException{
		SheetCell cell=null;
		SheetCell preChildCell=null;
		for(int i=0,size=generic.getChildSize();i<size;i++){
			cell=generic.getSheetCell(i);
			parseSheetCellSpan(cell, top);
			if(i==0){
				parseSheetCellCoordinate(cell, generic.getX(), generic.getY(), top);
			}else{
				preChildCell=generic.getSheetCell(i-1);
				if(top)
					parseSheetCellCoordinate(cell,preChildCell.getX()+preChildCell.getXspan(),generic.getY(), top);
				else	
				parseSheetCellCoordinate(cell,preChildCell.getX(),preChildCell.getY()+preChildCell.getYspan(), top);
			}
		}
	}
	
	
	/**
	 * 解析sheetCell的横跨列和纵跨列
	 * @param cell
	 * @param top 
	 * @return
	 */
	private int parseSheetCellSpan(SheetCell cell,boolean top){
		int span =0;
		int childCount=cell.getChildSize();
		if(childCount==0){
			return 1;
		}
		for(int i=0;i<childCount;i++){
			if(cell.getSheetCell(i)!=null)
				span += parseSheetCellSpan(cell.getSheetCell(i),top);
		}
		
		if(top){
			cell.setXspan(span);
		}else{
			cell.setYspan(span);
		}
		
		return span;
	}
	
	/**
	 * 设置sheetCell的所有子节点坐标(x,y)
	 * @param cell
	 * @param x
	 * @param y
	 * @param flag
	 */
	private void parseSheetCellCoordinate(SheetCell cell,int x,int y,boolean flag){
		cell.setX(x);
		cell.setY(y);
		int childCount = cell.getChildSize();//
		SheetCell childCell=null;
		SheetCell preChildCell=null;
		int count=0;
		for(int i=0;i<childCount;i++){
			childCell = cell.getSheetCell(i);
			if(i==0){
				if(flag){
					setSheetCellCoordinate(childCell, x, y+1);
					//childCell.setX(x);
					//childCell.setY(y+1);
				}else{
					setSheetCellCoordinate(childCell, x+1, y);
					//childCell.setX(x+1);
					//childCell.setY(y);
				}
			}else{
				preChildCell= cell.getSheetCell(i-1);
				if(flag){
					setSheetCellCoordinate(childCell,preChildCell.getX()+preChildCell.getXspan(), preChildCell.getY());
					//childCell.setX(preChildCell.getX()+preChildCell.getXspan());
					//childCell.setY(preChildCell.getY());
				}else{
					setSheetCellCoordinate(childCell,preChildCell.getX(), preChildCell.getY()+preChildCell.getYspan());
					//childCell.setX(preChildCell.getX());
					//childCell.setY(preChildCell.getY()+preChildCell.getYspan());
				}
			}
			count=childCell.getChildSize();
			if(count>0){
				parseSheetCellCoordinate(childCell, childCell.getX(), childCell.getY(), flag);
			}
		}
	} 


	private void setSheetCellCoordinate(SheetCell cell,int x,int y){
		cell.setX(x);
		cell.setY(y);
	}

}
